/********************************************************************************
* @file    led_pwm.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-06-14
* @brief   LED灯光，PWM控制
* @example

在[business_function.h]中配置PWM。 [APP LED]-[Light driven mode] / [PWM]-[TIM1 switch]
#include "ls_syscfg.h"
#include "bsp_pwm.h"
#include "app_led.h"
// 初始化PWM功能
bsp_pwm_init();
// 初始化APP_LED(创建软定时器)
app_led_init();
// 关闭灯光
app_led_indicate(LED_DRIVEN_PWM, APP_LED_ID_0, LED_TYPE_OFF, 0, 0);
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#include "app_led.h"
#include "bsp_pwm.h"
#include "os_api.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Define ------------------------------------------------------------*/
/**
 * @note   [警告] 宏定义函数的参数要使用括号，防止意外
 */
#define PWM_SET_OFF(DIR, PWMX, PERIOD_MAX)              \
    do                                                  \
    {                                                   \
        if (DIR)                                        \
            bsp_pwm_set_pulse(PWMX, 0);                 \
        else                                            \
            bsp_pwm_set_pulse(PWMX, PERIOD_MAX+1);      \
    } while (0U)

#define PWM_SET_VAL(DIR, PWMX, PERIOD, PERIOD_MAX)        \
    do                                                    \
    {                                                     \
        if (DIR)                                          \
            bsp_pwm_set_pulse(PWMX, PERIOD);              \
        else                                              \
            bsp_pwm_set_pulse(PWMX, PERIOD_MAX+1-PERIOD); \
    } while (0U)

#define PWM_MAX_VAL_CONSTRAINT(PERIOD, PERIOD_MAX)      \
    do                                                  \
    {                                                   \
        if (PERIOD > PERIOD_MAX+1)                      \
        {                                               \
            PERIOD = PERIOD_MAX+1;                      \
        }                                               \
    } while (0U)

/* Private Macro -------------------------------------------------------------*/
#if LS_TIM1_EN
#if LS_PWM0_EN
static void timer_pwm0_light_control(void const *arg);
#endif

#if LS_PWM1_EN
static void timer_pwm1_light_control(void const *arg);
#endif

#if LS_PWM2_EN
static void timer_pwm2_light_control(void const *arg);
#endif

#if LS_PWM3_EN
static void timer_pwm3_light_control(void const *arg);
#endif
#endif

#if LS_TIM2_EN
#if LS_PWM4_EN
static void timer_pwm4_light_control(void const *arg);
#endif

#if LS_PWM5_EN
static void timer_pwm5_light_control(void const *arg);
#endif

#if LS_PWM6_EN
static void timer_pwm6_light_control(void const *arg);
#endif

#if LS_PWM7_EN
static void timer_pwm7_light_control(void const *arg);
#endif
#endif

#if LS_TIM3_EN
#if LS_PWM8_EN
static void timer_pwm8_light_control(void const *arg);
#endif

#if LS_PWM9_EN
static void timer_pwm9_light_control(void const *arg);
#endif

#if LS_PWM10_EN
static void timer_pwm10_light_control(void const *arg);
#endif

#if LS_PWM11_EN
static void timer_pwm11_light_control(void const *arg);
#endif
#endif

/* Private Typedef -----------------------------------------------------------*/
static bool g_app_led_init = false;
// 定义led灯光结构体类型
typedef struct
{
    app_led_id_t     led_id;               // 组号
    app_led_type_t   type;                 // 0--灭灯  1--常亮  2--呼吸  3--快闪
    bool             level_logic;          // 0--低电平亮  1--高电平亮
    char            *timer_id;             // 软定时器id
    uint32_t         period_max;           // 重装载值(最大值)
    uint32_t         period;               // 重装载值(控制值)
    uint16_t         cycle_time;           // 定时器轮询时间ms(灭灯和常亮只执行一次)
    uint16_t         crest_time;           // 波峰：最高亮度保持时间ms
    uint16_t         trough_time;          // 波谷：最低亮度保持时间ms
    // 下面不用填写，仅用于临时计算
    uint8_t          temp_dir;             // 用于方向 0--up 1--keep 2--down
    uint16_t         temp_times;           // 用于计次
} app_led_t;

// 定义软定时器，用于实现灯光效果
#if LS_TIM1_EN
#if LS_PWM0_EN
os_timer_def(pwm0, timer_pwm0_light_control);
app_led_t app_led_pwm0 = {APP_LED_ID_0, LED_TYPE_OFF, LS_TIM1_LEVEL_LOGIC, NULL, LS_TIM1_PERIOD, 0, 0, 1, 0};
#endif

#if LS_PWM1_EN
os_timer_def(pwm1, timer_pwm1_light_control);
app_led_t app_led_pwm1 = {APP_LED_ID_1, LED_TYPE_OFF, LS_TIM1_LEVEL_LOGIC, NULL, LS_TIM1_PERIOD, 0, 0, 1, 0};
#endif

#if LS_PWM2_EN
os_timer_def(pwm2, timer_pwm2_light_control);
app_led_t app_led_pwm2 = {APP_LED_ID_2, LED_TYPE_OFF, LS_TIM1_LEVEL_LOGIC, NULL, LS_TIM1_PERIOD, 0, 0, 1, 0};
#endif

#if LS_PWM3_EN
os_timer_def(pwm3, timer_pwm3_light_control);
app_led_t app_led_pwm3 = {APP_LED_ID_3, LED_TYPE_OFF, LS_TIM1_LEVEL_LOGIC, NULL, LS_TIM1_PERIOD, 0, 0, 1, 0};
#endif
#endif

#if LS_TIM2_EN
#if LS_PWM4_EN
app_led_t app_led_pwm4 = {APP_LED_ID_4, LED_TYPE_OFF, LS_TIM2_LEVEL_LOGIC, NULL, LS_TIM2_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm4, timer_pwm4_light_control);
#endif

#if LS_PWM5_EN
app_led_t app_led_pwm5 = {APP_LED_ID_5, LED_TYPE_OFF, LS_TIM2_LEVEL_LOGIC, NULL, LS_TIM2_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm5, timer_pwm5_light_control);
#endif

#if LS_PWM6_EN
app_led_t app_led_pwm6 = {APP_LED_ID_6, LED_TYPE_OFF, LS_TIM2_LEVEL_LOGIC, NULL, LS_TIM2_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm6, timer_pwm6_light_control);
#endif

#if LS_PWM7_EN
app_led_t app_led_pwm7 = {APP_LED_ID_7, LED_TYPE_OFF, LS_TIM2_LEVEL_LOGIC, NULL, LS_TIM2_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm7, timer_pwm7_light_control);
#endif
#endif

#if LS_TIM3_EN
#if LS_PWM8_EN
app_led_t app_led_pwm8 = {APP_LED_ID_8, LED_TYPE_OFF, LS_TIM3_LEVEL_LOGIC, NULL, LS_TIM3_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm8, timer_pwm8_light_control);
#endif

#if LS_PWM9_EN
app_led_t app_led_pwm9 = {APP_LED_ID_9, LED_TYPE_OFF, LS_TIM3_LEVEL_LOGIC, NULL, LS_TIM3_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm9, timer_pwm9_light_control);
#endif

#if LS_PWM10_EN
app_led_t app_led_pwm10 = {APP_LED_ID_10, LED_TYPE_OFF, LS_TIM3_LEVEL_LOGIC, NULL, LS_TIM3_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm10, timer_pwm10_light_control);
#endif

#if LS_PWM11_EN
app_led_t app_led_pwm11 = {APP_LED_ID_11, LED_TYPE_OFF, LS_TIM3_LEVEL_LOGIC, NULL, LS_TIM3_PERIOD, 0, 0, 1, 0};
os_timer_def(pwm11, timer_pwm11_light_control);
#endif
#endif

/* Private Function Prototypes ----------------------------------------------*/
#if LS_TIM1_EN || LS_TIM2_EN || LS_TIM3_EN
/********************[灯光类型]对内接口函数*************************************/
/**
 * @brief  关闭灯光
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_off(app_led_t *app_led)
{
    PWM_SET_OFF(app_led->level_logic, (bsp_pwm_t)(app_led->led_id), app_led->period_max);
}

/**
 * @brief  灯光常亮
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_light(app_led_t *app_led)
{
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->period, app_led->period_max);
}

/**
 * @brief  灯光由暗变亮
 * @note   渐变效果由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_rise_slowly(app_led_t *app_led)
{
    if (app_led->type != LED_TYPE_RISE_SLOWLY)
    {
        return;
    }

    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);

    app_led->temp_times++;

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->temp_times, app_led->period_max);

    if (app_led->temp_times == app_led->period)
    {
        return;
    }

    os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}

/**
 * @brief  灯光由暗变亮(伴随闪烁)
 * @note   渐变效果由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_rise_slowly_twinkle(app_led_t *app_led)
{
    static bool twinkle_flag = false;
    static uint8_t twinkle_time_tick = 0;
    static uint16_t temp = 0;
    uint16_t twinkle_time = app_led->crest_time / 2 / app_led->cycle_time;

    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);

    app_led->temp_times++;
    twinkle_time_tick ++;
    if (twinkle_time_tick >= twinkle_time)
    {
        twinkle_time_tick = 0;
        // 伴随闪烁
        if (twinkle_flag == 0)
        {
            temp = app_led->temp_times;
            twinkle_flag = 1;
        }
        else
        {
            temp = 0;
            twinkle_flag = 0;
        }
    }
    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                temp, app_led->period_max);

    if (app_led->temp_times == app_led->period)
    {
        PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                    app_led->period, app_led->period_max);
        return;
    }

    os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}


/**
 * @brief  灯光由暗变亮(伴随闪烁) 带常亮保持 灭灯保持
 * @note   渐变效果由cycle_time决定
 * @param  *app_led: led灯光结构体指针
// last1 常亮时间(10ms)高8,灭灯时间(10ms)低8
 */
static void led_type_rise_slowly_twinkle_light_off_loop(app_led_t *app_led)
{
    static bool twinkle_flag = false;
    static uint8_t twinkle_time_tick = 0;
    static uint16_t temp = 0;
    uint16_t time = 0;
    uint16_t twinkle_time = app_led->crest_time / 2 / app_led->cycle_time;

    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);

    if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 0;
        app_led->temp_times = 0;
        PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                    0, app_led->period_max);
        time = (app_led->trough_time & 0x00FF)*10;
        time = time > 0 ? time : 1;
        os_timer_start((os_timer_id)(app_led->timer_id), time);
        return;
    }

    app_led->temp_times++;
    twinkle_time_tick ++;
    if (twinkle_time_tick >= twinkle_time)
    {
        twinkle_time_tick = 0;
        // 伴随闪烁
        if (twinkle_flag == 0)
        {
            temp = app_led->temp_times;
            twinkle_flag = 1;
        }
        else
        {
            temp = 0;
            twinkle_flag = 0;
        }
    }
    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                temp, app_led->period_max);

    if (app_led->temp_times == app_led->period)
    {
        app_led->temp_dir = 1;
        time = (app_led->trough_time >> 8) * 10;
        time = time > 0 ? time : 1;
        PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                    app_led->period, app_led->period_max);
        os_timer_start((os_timer_id)(app_led->timer_id), time);
        return;
    }
    os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}

/**
 * @brief  灯光由亮变暗
 * @note   渐变效果由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_fall_slowly(app_led_t *app_led)
{
    if (app_led->type != LED_TYPE_FALL_SLOWLY)
    {
        return;
    }

    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    app_led->temp_times++;
    if (app_led->temp_times > app_led->period)
    {
        led_type_off(app_led);
        return;
    }
    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                (app_led->period - app_led->temp_times), app_led->period_max);
    os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}

/**
 * @brief  灯光呼吸效果
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_breath(app_led_t *app_led)
{
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t time = 0;

    if (app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = app_led->crest_time > 0 ? app_led->crest_time : 1;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
    }

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->temp_times, app_led->period_max);

    if (app_led->temp_times == (app_led->period))
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == 0)
    {
        app_led->temp_dir = 0;
        time = app_led->trough_time > 0 ? app_led->trough_time : 1;
        goto end;
    }
    time = app_led->cycle_time > 0 ? app_led->cycle_time : 1;
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
 * @brief  车灯灯光呼吸效果
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_breath_lamp(app_led_t *app_led)
{
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t time = 0;

    if (app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = app_led->crest_time > 0 ? app_led->crest_time : 1;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
    }

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->temp_times, app_led->period_max);

    if (app_led->temp_times == (app_led->period))
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == 0)
    {
        app_led->temp_dir = 0;
        time = app_led->trough_time > 0 ? app_led->trough_time : 1;
        goto end;
    }
    if (app_led->level_logic == 1)
    {
        if (app_led->temp_dir == 0)
        {
            if (app_led->temp_times < (app_led->period >> 2))
            {
                time = 15;
                goto end;
            }
            else if (app_led->temp_times < app_led->period / 3)
            {
                time = 9;
                goto end;
            }
            else if (app_led->temp_times < (app_led->period >> 1))
            {
                time = 5;
                goto end;
            }
        }
    }
    else
    {
        if (app_led->temp_dir == 2)
        {
            if (app_led->temp_times < (app_led->period >> 2))
            {
                time = 5;
                goto end;
            }
            else if (app_led->temp_times < app_led->period / 3)
            {
                time = 9;
                goto end;
            }
            else if (app_led->temp_times < (app_led->period >> 1))
            {
                time = 15;
                goto end;
            }
        }
    }
    time = app_led->cycle_time > 0 ? app_led->cycle_time : 1;
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
 * @brief  灯光呼吸+闪烁效果（含峰顶 峰谷）
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_breath_twinkle(app_led_t *app_led)
{
    static bool twinkle_flag = false;
    static uint8_t twinkle_time_tick = 0;
    static uint16_t temp = 0;
    uint16_t twinkle_time = app_led->crest_time / app_led->cycle_time;
    uint16_t time = 0;

    if (app_led->type != LED_TYPE_BREATH_TWINKLE)
    {
        return;
    }
    twinkle_time_tick ++;
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);

    if (app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = 1;
        twinkle_flag = 0;
        twinkle_time_tick = 0;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
    }
    if (twinkle_time_tick >= twinkle_time)
    {
        twinkle_time_tick = 0;
        // 伴随闪烁
        if (twinkle_flag == 0)
        {
            temp = app_led->temp_times;
            twinkle_flag = 1;
        }
        else
        {
            temp = 0;
            twinkle_flag = 0;
        }
    }
    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                temp, app_led->period_max);

    if (app_led->temp_times == (app_led->period))
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == 0)
    {
        app_led->temp_dir = 0;
        time = 1;
        twinkle_flag = 1;
        twinkle_time_tick = 0;
        goto end;
    }

    time = app_led->cycle_time > 0 ? app_led->cycle_time : 1;
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
 * @brief  灯光闪烁
 * @note   闪烁频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_twinkle(app_led_t *app_led)
{
    if (app_led->type != LED_TYPE_TWINKLE)
    {
        return;
    }

    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t temp = 0;
    if (app_led->temp_dir == 0)
    {
        temp = app_led->period;

        app_led->temp_dir = 1;
    }
    else
    {
        temp = 0;
        app_led->temp_dir = 0;
    }

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                temp, app_led->period_max);
    os_timer_start((os_timer_id)(app_led->timer_id), app_led->cycle_time);
}

/**
 * @brief  灯光SOS灯效
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_sos(app_led_t *app_led)
{
    if (app_led->type != LED_TYPE_SOS)
    {
        return;
    }

    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t temp = 0;
    uint16_t time = 0;
    if (app_led->temp_dir == 0)
    {
        app_led->temp_dir = 1;
        temp = app_led->period;
        time = 100;
        goto end;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_times++;
        app_led->temp_dir = 0;
        if (app_led->temp_times > 2)
        {
            app_led->temp_times = 0;
            app_led->temp_dir = 2;
        }
        temp = 0;
        time = 200;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_dir = 3;
        temp = app_led->period;
        time = 800;
        goto end;
    }
    else if (app_led->temp_dir == 3)
    {
        app_led->temp_times++;
        app_led->temp_dir = 2;
        if (app_led->temp_times > 2)
        {
            app_led->temp_times = 0;
            app_led->temp_dir   = 0;
        }
        temp = 0;
        time = 200;
        goto end;
    }
    else
    {
        app_led->temp_dir = 0;
    }
end:
    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                temp, app_led->period_max);
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
 * @brief  伴随闪烁效果上升到指定高度X，再从X上升到100。不带闪烁。然后缓慢下降直到灭灯
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
            cycle_time 高8位 上升指定高度时间周期ms   低8位 上升到100时间周期ms
            crest_time 闪烁时间间隔ms
            trough_time 高8位 下降指到灭灯时间周期（单位10ms）   低8位 灭灯时间周期（单位10ms）
 */
void led_type_rise_slowly_twinkle_rise_fall_off_loop(app_led_t *app_led)
{
    static bool twinkle_flag = false;
    static uint8_t twinkle_time_tick = 0;
    uint16_t twinkle_time = app_led->crest_time / (app_led->cycle_time >> 8);
    static uint16_t temp = 0;

    twinkle_time_tick ++;
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t time = 0;

    if (app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = 1;
        twinkle_flag = 0;
        twinkle_time_tick = 0;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
    }
    if (app_led->temp_dir == 0 && twinkle_time_tick >= twinkle_time && (app_led->temp_times < (app_led->period_max / 2)))
    {
        twinkle_time_tick = 0;
        // 伴随闪烁
        if (twinkle_flag == 0)
        {
            temp = app_led->temp_times;
            twinkle_flag = 1;
        }
        else
        {
            temp = 0;
            twinkle_flag = 0;
        }
    }
    else
    {
        temp = app_led->temp_times;
    }
    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                temp, app_led->period_max);

    if (app_led->temp_times == (app_led->period))
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == 0)
    {
        app_led->temp_dir = 0;
        time = (app_led->trough_time & 0x00FF)*10;
        twinkle_flag = 1;
        twinkle_time_tick = 0;
        goto end;
    }
    if (app_led->temp_dir == 0)
    {
        if ((app_led->temp_times < (app_led->period_max / 2)))
        {
            time = app_led->cycle_time >> 8;
        }
        else
        {
            time = app_led->cycle_time & 0x00FF;
        }
    }
    else if (app_led->temp_dir == 2)
    {
        time = (app_led->trough_time >> 8) / 10;
    }
end:
    time = time > 0 ? time : 1;
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
* @brief  灯光先灭灯指定时间，再缓慢上升，再下降到指定亮度并保持常亮
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_off_rise_slowly_fall_light(app_led_t *app_led)
{
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t time = 0;

    if (app_led->temp_times == 0 && app_led->temp_dir == 0)
    {
        PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                    0, app_led->period_max);
        os_timer_start((os_timer_id)(app_led->timer_id), app_led->crest_time);
        app_led->temp_times++;
        return;
    }
    else if (app_led->temp_times != 0 && app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = 1;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
        if (app_led->temp_times == app_led->trough_time)
        {
            return;
        }
    }

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->temp_times, app_led->period_max);

    if (app_led->temp_times == (app_led->period))
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == 0)
    {
        app_led->temp_dir = 0;
        time = 1;
        goto end;
    }
    if (app_led->temp_times < app_led->trough_time)
    {
        time = (app_led->cycle_time>>8) > 0 ? (app_led->cycle_time>>8) : 1;
    }
    else
    {
        time = (app_led->cycle_time&0x00ff) > 0 ? (app_led->cycle_time&0x00ff) : 1;
    }
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
 * @brief  灯光呼吸效果(半呼状态，不灭完)
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_breath_top_low(app_led_t *app_led)
{
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t time = 0;

    if (app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = 1;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
    }

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->temp_times, app_led->period_max);

    if (app_led->temp_times == (app_led->trough_time>>8))
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == (app_led->trough_time & 0x00ff))
    {
        app_led->temp_dir = 0;
        time = 1;
        goto end;
    }
    if (app_led->temp_dir == 0)
    {
        time = (app_led->cycle_time>>8) > 0 ? (app_led->cycle_time>>8) : 1;
    }
    else if (app_led->temp_dir == 2)
    {
        time = (app_led->cycle_time&0x00ff) > 0 ? (app_led->cycle_time&0x00ff) : 1;
    }
    time = time > 0 ? time : 1;
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}

/**
 * @brief  灯光呼吸效果(半呼状态，不灭完)
 * @note   呼吸频率由cycle_time决定
 * @param  *app_led: led灯光结构体指针
 */
static void led_type_rise_slowly_fall_slowly_off_loop(app_led_t *app_led)
{
    PWM_MAX_VAL_CONSTRAINT(app_led->period, app_led->period_max);
    uint16_t time = 0;

    if (app_led->temp_dir == 0)
    {
        app_led->temp_times++;
    }
    else if (app_led->temp_dir == 1)
    {
        app_led->temp_dir = 2;
        time = 1;
        goto end;
    }
    else if (app_led->temp_dir == 2)
    {
        app_led->temp_times--;
    }

    PWM_SET_VAL(app_led->level_logic, (bsp_pwm_t)(app_led->led_id),
                app_led->temp_times, app_led->period_max);

    if (app_led->temp_times == app_led->period)
    {
        app_led->temp_dir = 1;
    }
    else if (app_led->temp_times == 0)
    {
        app_led->temp_dir = 0;
        time = (app_led->trough_time&0x00ff)*10 > 0 ? (app_led->trough_time&0x00ff)*10 : 1;
        goto end;
    }
    if (app_led->temp_dir == 0)
    {
        time = (app_led->cycle_time>>8) > 0 ? (app_led->cycle_time>>8) : 1;
    }
    else if (app_led->temp_dir == 2)
    {
        if (app_led->temp_times < app_led->crest_time)
        {
            time = (app_led->trough_time>>8) > 0 ? (app_led->trough_time>>8) : 1;
        }
        else
        {
            time = (app_led->cycle_time&0x00ff) > 0 ? (app_led->cycle_time&0x00ff) : 1;
        }
    }
    time = time > 0 ? time : 1;
end:
    os_timer_start((os_timer_id)(app_led->timer_id), time);
}
/************************************[软定时器][回调函数]灯光操作************************************/

static void timer_pwm_light_control(app_led_t *app_led)
{
    if (app_led->type == LED_TYPE_OFF)
    {
        led_type_off(app_led);
    }
    else if (app_led->type == LED_TYPE_LIGHT)
    {
        led_type_light(app_led);
    }
    else if (app_led->type == LED_TYPE_BREATH)
    {
        led_type_breath(app_led);
    }
    else if (app_led->type == LED_TYPE_BREATH_LAMP)
    {
        led_type_breath_lamp(app_led);
    }
    else if (app_led->type == LED_TYPE_TWINKLE)
    {
        led_type_twinkle(app_led);
    }
    else if (app_led->type == LED_TYPE_SOS)
    {
        led_type_sos(app_led);
    }
    else if (app_led->type == LED_TYPE_RISE_SLOWLY)
    {
        led_type_rise_slowly(app_led);
    }
    else if (app_led->type == LED_TYPE_FALL_SLOWLY)
    {
        led_type_fall_slowly(app_led);
    }
    else if (app_led->type == LED_TYPE_RISE_SLOWLY_TWINKLE)
    {
        led_type_rise_slowly_twinkle(app_led);
    }
    else if (app_led->type == LED_TYPE_RISE_SLOWLY_TWINKLE_LIGHT_OFF_LOOP)
    {
        led_type_rise_slowly_twinkle_light_off_loop(app_led);
    }
    else if (app_led->type == LED_TYPE_BREATH_TWINKLE)
    {
        led_type_breath_twinkle(app_led);
    }
    else if (app_led->type == LED_TYPE_RISE_SLOWLY_TWINKLE_RISE_FALL_OFF_LOOP)
    {
        led_type_rise_slowly_twinkle_rise_fall_off_loop(app_led);
    }
    else if (app_led->type == LED_TYPE_OFF_RISE_SLOWLY_FALL_LIGHT)
    {
        led_type_off_rise_slowly_fall_light(app_led);
    }
    else if (app_led->type == LED_TYPE_BREATH_TOP_LOW)
    {
        led_type_breath_top_low(app_led);
    }
    else if (app_led->type == LED_TYPE_RISE_SLOWLY_FALL_SLOWLY_OFF_LOOP)
    {
        led_type_rise_slowly_fall_slowly_off_loop(app_led);
    }
}
#endif
#if LS_TIM1_EN
#if LS_PWM0_EN
/**
 * @brief  [软定时器回调函数][PWM0] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm0_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm0);
}
#endif

#if LS_PWM1_EN
/**
 * @brief  [软定时器回调函数][PWM1] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm1_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm1);
}
#endif

#if LS_PWM2_EN
/**
 * @brief  [软定时器回调函数][PWM2] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm2_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm2);
}
#endif

#if LS_PWM3_EN
/**
 * @brief  [软定时器回调函数][PWM3] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm3_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm3);
}
#endif
#endif

#if LS_TIM2_EN
#if LS_PWM4_EN
/**
 * @brief  [软定时器回调函数][PWM4] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm4_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm4);
}
#endif

#if LS_PWM5_EN
/**
 * @brief  [软定时器回调函数][PWM5] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm5_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm5);
}
#endif

#if LS_PWM6_EN
/**
 * @brief  [软定时器回调函数][PWM6] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm6_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm6);
}
#endif

#if LS_PWM7_EN
/**
 * @brief  [软定时器回调函数][PWM7] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm7_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm7);
}
#endif
#endif

#if LS_TIM3_EN
#if LS_PWM8_EN
/**
 * @brief  [软定时器回调函数][PWM8] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm8_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm8);
}
#endif

#if LS_PWM9_EN
/**
 * @brief  [软定时器回调函数][PWM9] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm9_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm9);
}
#endif

#if LS_PWM10_EN
/**
 * @brief  [软定时器回调函数][PWM10] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm10_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm10);
}
#endif

#if LS_PWM11_EN
/**
 * @brief  [软定时器回调函数][PWM11] 执行对应灯光效果
 * @note   采用定时器轮询实现灯效
 */
static void timer_pwm11_light_control(void const *arg)
{
    timer_pwm_light_control(&app_led_pwm11);
}
#endif
#endif

/**
  * @brief  通过led_id获取结构体指针
  * @param  led_id 灯光id号
  * @return NULL--无效  其他则有效值
  */
static app_led_t *get_app_led(app_led_id_t led_id)
{
    if (led_id == APP_LED_ID_0)
    {
#if LS_TIM1_EN && LS_PWM0_EN
        return &app_led_pwm0;
#else
        return NULL;
#endif
    }
#if LS_TIM1_EN && LS_PWM1_EN
    else if (led_id == APP_LED_ID_1)
    {
        return &app_led_pwm1;
    }
#endif
#if LS_TIM1_EN && LS_PWM2_EN
    else if (led_id == APP_LED_ID_2)
    {
        return &app_led_pwm2;
    }
#endif
#if LS_TIM1_EN && LS_PWM3_EN
    else if (led_id == APP_LED_ID_3)
    {
        return &app_led_pwm3;
    }
#endif
#if LS_TIM2_EN && LS_PWM4_EN
    else if (led_id == APP_LED_ID_4)
    {
        return &app_led_pwm4;
    }
#endif
#if LS_TIM2_EN && LS_PWM5_EN
    else if (led_id == APP_LED_ID_5)
    {
        return &app_led_pwm5;
    }
#endif
#if LS_TIM2_EN && LS_PWM6_EN
    else if (led_id == APP_LED_ID_6)
    {
        return &app_led_pwm6;
    }
#endif
#if LS_TIM2_EN && LS_PWM7_EN
    else if (led_id == APP_LED_ID_7)
    {
        return &app_led_pwm7;
    }
#endif
#if LS_TIM3_EN && PWM8_EN
    else if (led_id == APP_LED_ID_8)
    {
        return &app_led_pwm8;
    }
#endif
#if LS_TIM3_EN && PWM9_EN
    else if (led_id == APP_LED_ID_9)
    {
        return &app_led_pwm9;
    }
#endif
#if LS_TIM3_EN && PWM10_EN
    else if (led_id == APP_LED_ID_10)
    {
        return &app_led_pwm10;
    }
#endif
#if LS_TIM3_EN && PWM11_EN
    else if (led_id == APP_LED_ID_11)
    {
        return &app_led_pwm11;
    }
#endif
    return NULL;
}

/* Public Function Prototypes -----------------------------------------------*/
/**
 * @brief  [app层][PWM相关初始化] 定义软定时器和参数设置
 */
void led_pwm_init(void)
{
    if (g_app_led_init)
    {
        return;
    }
#if LS_TIM1_EN || LS_TIM2_EN || LS_TIM3_EN
    uint32_t timer_pwm_ret = 0;
#endif
#if LS_TIM1_EN
#if LS_PWM0_EN
    app_led_pwm0.timer_id    = (char *)os_timer_create(os_timer(pwm0), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if LS_PWM1_EN
    app_led_pwm1.timer_id    = (char *)os_timer_create(os_timer(pwm1), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if LS_PWM2_EN
    app_led_pwm2.timer_id    = (char *)os_timer_create(os_timer(pwm2), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if LS_PWM3_EN
    app_led_pwm3.timer_id    = (char *)os_timer_create(os_timer(pwm3), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#endif

#if LS_TIM2_EN
#if LS_PWM4_EN
    app_led_pwm4.timer_id    = (char *)os_timer_create(os_timer(pwm4), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if LS_PWM5_EN
    app_led_pwm5.timer_id    = (char *)os_timer_create(os_timer(pwm5), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if LS_PWM6_EN
    app_led_pwm6.timer_id    = (char *)os_timer_create(os_timer(pwm6), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if LS_PWM7_EN
    app_led_pwm7.timer_id    = (char *)os_timer_create(os_timer(pwm7), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#endif

#if LS_TIM3_EN
#if PWM8_EN
    app_led_pwm8.timer_id    = (char *)os_timer_create(os_timer(pwm8), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if PWM9_EN
    app_led_pwm9.timer_id    = (char *)os_timer_create(os_timer(pwm9), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if PWM10_EN
    app_led_pwm10.timer_id    = (char *)os_timer_create(os_timer(pwm10), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#if PWM11_EN
    app_led_pwm11.timer_id    = (char *)os_timer_create(os_timer(pwm11), OS_TIMER_ONCE, &timer_pwm_ret);
#endif
#endif
    g_app_led_init = true;
}

/**
 * @brief  得到当前组号的PWM值
 * @param  led_id: led组号
 * @retval 当前组号的PWM值
 */
uint16_t app_led_pwm_get_current_period(app_led_id_t led_id)
{
    app_led_t *app_led = get_app_led(led_id);
    return app_led->period;
}

/**
 * @brief  得到当前组号的灯光模式
 * @param  led_id: led组号
 * @retval 当前组号的灯光模式
 */
app_led_type_t app_led_pwm_get_current_type(app_led_id_t led_id)
{
    app_led_t *app_led = get_app_led(led_id);
    return app_led->type;
}

/**
  * @brief  LED操作
  * @param  led_id led组号
  * @param  type 灯光类型
  * @param  cycle_time 灯光周期(ms) 定时器轮询时间(灭灯和常亮只执行一次)
  * @param  period 重装载值(控制值)
  * @param  crest_time: 波峰：最高亮度保持时间ms
  * @param  trough_time: 波谷：最低亮度保持时间ms
  * @return 0--false 1--true
  */
bool app_led_pwm_ioctl(app_led_id_t led_id, app_led_type_t type, uint16_t cycle_time,
                       uint32_t period, uint16_t crest_time, uint16_t trough_time)
{
    app_led_t *led_info = NULL;

    led_info = get_app_led(led_id);
    if (led_info == NULL)
    {
        return false;
    }

    led_info->temp_dir    = 0;
    led_info->temp_times  = 0;
    led_info->cycle_time  = cycle_time;
    led_info->period      = period;
    led_info->type        = type;
    led_info->crest_time  = crest_time;
    led_info->trough_time = trough_time;

    os_timer_start((os_timer_id)(led_info->timer_id), 1);
    return true;
}
